-
Notifications
You must be signed in to change notification settings - Fork 12.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Print a message on OOM #30801
Print a message on OOM #30801
Conversation
(rust_highfive has picked a reviewer for you, use r? to override) |
Does this actually work? That is, does |
I checked that the implementation of |
Actually, I'll take that back, it seems that |
Since this is mainly going to be useful on unix platforms (windows will display a message box from the abort), I could simply make it unix-only where |
I instead made the OOM handler reset itself once it is invoked so that any recursive failure to allocate memory will simply fall back to the old behavior of aborting without a message. |
Even on Windows it would be nice to have a message because often times when running a program in the console, the message box doesn't pop up, and even when it does it doesn't tell you anything useful other than the program crashed. Since most of the time people will hit oom from accidentally passing a silly huge number number to |
Couldn't the error string just be stored as a static? |
@mmcco Sure, you could have a const array of u16 and write that directly. If that is unreasonable since the message is ascii you could also just cast the u8 codeunits to u16 and store it in a buffer on the stack and write that. |
@Amanieu yes as you've found this will allocate memory on Windows, I think for two reasons:
@retep998 do you know of a guaranteed way to print to the console which is infallible? If so, we could use that vector for printing information. Otherwise I do agree that resetting the handler to the default "abort and die" seems reasonable right before we attempt to print. Note that this has implications on the multithreaded scenario, however, where if one thread is attempting to print and another hits OOM it'll take down the process without printing anything anyway. I believe that may be fixable by having a global mutex around the OOM handler, but that itself will be tricky to do. I'm a little hesitant about this as it's very tough to ensure there are 0 allocations along the way in the oom handler unless it's basically written from scratch. I would almost prefer that the handler in libstd is written in such a way that all the code is self-contained to be easily inspected for "this doesn't allocate". It'll be a little uglier, but much easier to audit and future-proof from accidental modifications |
One possibility would be to call |
@alexcrichton Remove the layers of abstraction? Just get |
I implemented a new version which uses separate platform-specific OOM handlers for windows & unix. I only tested the unix version, so there may be issues with the windows code. Here's a small test program which triggers an OOM: http://ix.io/nkx You may have to adjust the numbers if you are running on a 32-bit system. |
If that windows code does compile, then I'm pretty sure it'll work correctly. |
pub fn oom() -> ! { | ||
// Reset the OOM handler to avoid infinite loops if the OOM handler tries | ||
// to allocate memory and fails. | ||
let value = OOM_HANDLER.swap(default_oom_handler as *mut (), Ordering::SeqCst); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that with the changes below it should be fine to have this just be load
instead of swap
. I'm worried about the usefulness of the swap
here because if a bunch of threads hit OOM at the same time the process is likely to terminate without printing anything (the second thread will abort the process likely before the first prints).
The implementations below are pretty safe to audit for not having any allocations in them as well, I believe.
If |
@@ -58,6 +59,20 @@ pub fn init() { | |||
unsafe { | |||
assert!(signal(libc::SIGPIPE, libc::SIG_IGN) != !0); | |||
} | |||
|
|||
// A nicer handler for out-of-memory situations than the default one. This | |||
// one prints a message to stderr before aborting. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you expand this to explain:
- It's critical that this function doesn't have any allocations, so it shouldn't be using many abstractions.
- Errors are ignored here because there's not really anything else that can be done.
Looking good to me, thanks @Amanieu! |
Updated according to feedback. |
If |
use intrinsics; | ||
let msg = "fatal runtime error: out of memory\n"; | ||
unsafe { | ||
libc::write(libc::STDERR_FILENO, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rtabort!
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See @alexcrichton's comment:
I'm a little hesitant about this as it's very tough to ensure there are 0 allocations along the way in the oom handler unless it's basically written from scratch. I would almost prefer that the handler in libstd is written in such a way that all the code is self-contained to be easily inspected for "this doesn't allocate". It'll be a little uglier, but much easier to audit and future-proof from accidental modifications
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool.
@bors: r+ 03dd45a623b8deb1c528d4f65cda3023611cc119 |
⌛ Testing commit 03dd45a with merge efbbe04... |
💔 Test failed - auto-win-msvc-64-opt |
Oops, fixed. |
This adds the ability to override the default OOM behavior by setting a handler function. This is used by libstd to print a message when running out of memory instead of crashing with an obscure "illegal hardware instruction" error (at least on Linux). Fixes rust-lang#14674
This adds the ability to override the default OOM behavior by setting a handler function. This is used by libstd to print a message when running out of memory instead of crashing with an obscure "illegal hardware instruction" error (at least on Linux).
Fixes #14674